<!-- 数据字典组件 -->
<template>
  <div>
    <el-card>
      <!-- 面包屑导航区域 -->
      <el-breadcrumb>
        <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
        <el-breadcrumb-item>数据字典</el-breadcrumb-item>
        <span class="btn">
          <!-- 新增按钮区域 -->
          <el-button type="primary" size="medium" @click="addDictionaryData">新增</el-button>
          <!-- 批量删除按钮 -->
          <el-button type="danger" size="medium" @click="allDeleteBtn()">批量删除</el-button>
        </span>
      </el-breadcrumb>
      <span class="spnBorder"></span>
      <div class="serachFrom">
        <!-- 按钮区域 -->
        <p class="btn">
          <!-- <el-button type="primary" size="mini">导出</el-button> -->
        </p>
        <!-- 表单查询区域 -->
        <el-form :inline="true" :model="formInline" ref="queryFromRef" class="demo-form-inline">
          <el-form-item label="字典名称" prop="name">
            <el-col :span="20">
              <el-input v-model="formInline.name" placeholder="请输入字典名称"></el-input>
            </el-col>
          </el-form-item>
          <el-form-item label="字典类型" prop="type">
            <el-col :span="20">
              <el-input v-model="formInline.type" placeholder="请输入字典类型"></el-input>
            </el-col>
          </el-form-item>
          <el-form-item label="字典值" prop="value">
            <el-col :span="20">
              <el-input v-model="formInline.value" placeholder="请输入字典值"></el-input>
            </el-col>
          </el-form-item>
          <el-form-item class="itemBtns">
            <el-button type="primary" @click="searchBtn">查询</el-button>
            <el-button @click="resetBtn">重置</el-button>
          </el-form-item>
        </el-form>
      </div>

      <!-- 表格区域 -->
      <el-table
        :data="tableData"
        style="width: 100%;"
        @selection-change="handleSelectionChange"
        @expand-change="exChange"
        v-loading="pictLoading"
        element-loading-text="数据正在加载中..."
        element-loading-spinner="el-icon-loading"
      >
        <el-table-column type="expand" width="55">
          <!-- 渲染一级权限 -->
          <template slot-scope="scope">
            <el-table
              :data="scope.row.children"
              @selection-change="handleSelectionChange"
              :show-header="false"
              style="width: 100%"
            >
              <el-table-column type="selection"></el-table-column>
              <el-table-column prop="name" width="180" label="字典名称" align="center"></el-table-column>
              <el-table-column prop="type" label="字典类型" align="center"></el-table-column>
              <el-table-column prop="code" label="字典编码" align="center"></el-table-column>
              <el-table-column prop="value" label="字典值" align="center"></el-table-column>
              <el-table-column prop="orderNumber" label="排序" align="center"></el-table-column>
              <el-table-column prop="remark" label="备注" align="center"></el-table-column>
              <el-table-column label="操作" width="200" align="center">
                <template slot-scope="scope">
                  <el-button type="primary" plain size="mini" @click="editTableData(scope.row)">修改</el-button>
                  <el-button
                    type="danger"
                    plain
                    size="mini"
                    @click="deleteTableBtn(scope.row.id)"
                  >删除</el-button>
                </template>
              </el-table-column>
            </el-table>
          </template>
        </el-table-column>
        <el-table-column type="selection"></el-table-column>
        <el-table-column type="index" label="序号" align="center" width="50"></el-table-column>
        <el-table-column prop="name" label="字典名称" width="180" align="center"></el-table-column>
        <el-table-column prop="type" label="字典类型名称" align="center"></el-table-column>
        <el-table-column prop="code" label="字典编码" align="center"></el-table-column>
        <el-table-column prop="value" label="字典值" align="center"></el-table-column>
        <el-table-column prop="orderNumber" label="排序" align="center"></el-table-column>
        <el-table-column prop="remark" label="备注" align="center"></el-table-column>
        <el-table-column label="操作" width="200" align="center">
          <template slot-scope="scope">
            <el-button type="primary" plain size="mini" @click="editTableData(scope.row)">修改</el-button>
            <el-button type="danger" plain size="mini" @click="deleteTableBtn(scope.row.id)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页区域 -->
      <el-pagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="formInline.page"
        :page-sizes="[5, 10, 15, 20]"
        :page-size="formInline.limit"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
      ></el-pagination>
    </el-card>
    <!-- 新增对话框 -->
    <el-dialog
      :title="flag===true?'新增':'修改'"
      :visible.sync="addDictionaryDialogVisible"
      width="60%"
      @close="resetFromData"
    >
      <!-- 新增表单区域 -->
      <el-form
        :label-position="labelPosition"
        label-width="120px"
        :model="DialogVisibleData"
        :rules="DictionaryRules"
        ref="DictionaryRef"
      >
        <el-form-item label="字典名称" prop="name" class="inputWidth">
          <el-input v-model="DialogVisibleData.name" placeholder="请输入字典名称"></el-input>
        </el-form-item>
        <el-form-item label="字典类型" prop="typename" class="inputWidth inputRight">
          <el-cascader
            v-model="DialogVisibleData.typename"
            :options="options"
            :props="{ expandTrigger: 'hover' }"
            @change="dictionarySelect($event)"
            :disabled="disabledStr"
            placeholder="请选择字典类型"
          ></el-cascader>
        </el-form-item>
        <el-form-item label="字典编码" prop="code" class="inputWidth">
          <el-input v-model="DialogVisibleData.code" :disabled="disabledStr" placeholder="请输入字典编码"></el-input>
        </el-form-item>
        <el-form-item label="字典类型名称" prop="type" class="inputWidth inputRight">
          <el-input v-model="DialogVisibleData.type" :disabled="disabledSp" placeholder="请输入字典类型名称"></el-input>
        </el-form-item>
        <el-form-item label="字典值" prop="value" class="inputWidth">
          <el-input v-model="DialogVisibleData.value" :disabled="disabledStr" placeholder="请输入字典值"></el-input>
        </el-form-item>
        <el-form-item label="排序" prop="orderNumber" class="inputWidth inputRight">
          <el-input v-model="DialogVisibleData.orderNumber" type="number" :min="0"></el-input>
        </el-form-item>
        <el-form-item label="备注" prop="remark" style="width:97%;">
          <el-input type="textarea" v-model="DialogVisibleData.remark" :autosize="{ minRows: 3}"></el-input>
        </el-form-item>
        <!-- 图片上传区域 -->
        <el-form-item label="图片上传">
          <!-- action 是图片要上传到的后台API地址 -->
          <el-upload
            :action="uploadURL"
            list-type="picture"
            :headers="headerObj"
            :file-list="fileList"
            :on-change="handleChange"
            :on-success="handleSuccess"
            :on-remove="handleRemove"
          >
            <el-button size="small" type="primary" plain>点击上传</el-button>
          </el-upload>
        </el-form-item>
      </el-form>
      <!-- 按钮区域 -->
      <div class="dialogBot" slot="footer">
        <el-button @click="addDictionaryDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="addTableData" :disabled="isDisable">确 定</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
export default {
  data() {
    return {
      // 要查询表单对象
      formInline: {
        // 当前选中的页数
        page: 1,
        // 每页显示的数据条数
        limit: 10,
        name: '',
        type: '',
        value: '',
      },
      // 表格一级菜单数据
      tableData: [],
      // 表格二级级菜单数据
      // tableChildData: [],
      // 列表数据总条数
      total: 0,
      // 默认 新增/修改对话框隐藏
      addDictionaryDialogVisible: false,
      labelPosition: 'right',
      // 新增表单对象
      DialogVisibleData: {
        id: '',
        typename: [], // 字典类型名称
        name: '',
        type: '',
        code: '',
        value: '',
        orderNumber: 0,
        remark: '',
        parentId: '',
        // 图片的数组
        image: '',
      },
      // 上传图标显示列表
      fileList: [],
      // 对话框字典类型菜单数据
      options: [],
      // 列表数据加载时loading
      pictLoading: false,
      // 控制对话框标题显示
      flag: true,
      // 是否禁用input框
      disabledStr: true,
      // 当字典类型名称为一级菜单不禁止，二级菜单禁止
      disabledSp: false,
      // 添加表单验证规则对象
      DictionaryRules: {
        typename: [{ required: true, message: '请选择字典类型', trigger: 'blur' }],
        name: [{ required: true, message: '请输入字典名称', trigger: 'blur' }],
        type: [{ required: true, message: '请输入字典类型名称', trigger: 'blur' }],
        code: [{ required: true, message: '请输入字典编码', trigger: 'blur' }],
        value: [{ required: true, message: '请输入字典值', trigger: 'blur' }],
        orderNumber: [{ required: true, message: '请选择排序', trigger: 'blur' }],
      },
      // 批量删除是的ids数组数据
      ids: [],
      // 上传图片的URL地址
      uploadURL: 'http://172.17.135.116:8089/rescue-map/sys/dict/base64',
      // 图片上传组件的headers请求头对象
      headerObj: {
        BQTOKEN: window.sessionStorage.getItem('token'),
      },
      previewPath: '',
      previewVisible: false,
      isDisable: false, // 避免表单重复提交
    }
  },
  created() {
    this.getDictionaryList()
    // this.getDictionaryType()
  },
  methods: {
    // 获取列表数据
    async getDictionaryList() {
      this.pictLoading = true
      const { data: res } = await this.$http.get('/sys/dict/list_page', { params: { page: this.formInline.page, limit: this.formInline.limit } })
      console.log(res)
      this.pictLoading = false
      if (res.errorCode !== 200) return this.$message.error('获取数据列表失败！')
      this.tableData = res.data.list
      this.total = res.data.totalCount
    },
    // 监听当前选择的页数
    handleCurrentChange(currentPage) {
      this.formInline.page = currentPage
      this.getDictionaryList()
    },
    // 监听每页显示多少条数据
    handleSizeChange(pageSize) {
      this.formInline.limit = pageSize
      this.getDictionaryList()
    },
    // 监听表格列表展开事件
    async exChange(row) {
      console.log(row.id)
      const { data: res } = await this.$http.get('/sys/dict/list_page', { params: { parentId: row.id } })
      console.log(res.data.list)
      this.tableData.map(function (v) {
        if (v.id === row.id) {
          // console.log(v)
          v.children = res.data.list
        }
      })
    },
    // 获取对话框中字典类型数据
    async getDictionaryType() {
      const { data: res } = await this.$http.get('/sys/dict/name')
      if (res.errorCode !== 200) return this.$message.error('获取字典类型失败！')
      this.options = res.data
    },
    // 监听字典类型的变化
    dictionarySelect(e) {
      console.log(e)
      this.options.map((item) => {
        if (item.value === '一级菜单') {
          console.log(item.id)
          this.DialogVisibleData.parentId = item.id
          this.DialogVisibleData.type = ''
          this.disabledSp = false // 一级菜单可以输入
        } else {
          item.children.map((v) => {
            // let end = e.pop() // 获取数组的最后一个元素
            if (v.value === e[1]) {
              console.log(v.id)
              this.DialogVisibleData.parentId = v.id
              this.DialogVisibleData.type = v.type
              this.disabledSp = true // 二级菜单不能输入
            }
          })
        }
      })
    },
    // 点击新增按钮显示对话框
    addDictionaryData() {
      this.getDictionaryType() // 字典类型数据
      this.addDictionaryDialogVisible = true
      this.flag = true
      this.disabledStr = false
      this.disabledSp = false
      this.DialogVisibleData.typename = []
      this.DialogVisibleData.id = ''
      this.DialogVisibleData.parentId = ''
      this.DialogVisibleData.name = ''
      this.DialogVisibleData.type = ''
      this.DialogVisibleData.code = ''
      this.DialogVisibleData.value = ''
      this.DialogVisibleData.orderNumber = 0
      this.DialogVisibleData.remark = ''
      this.DialogVisibleData.image = ''
    },
    // 实现新增和修改功能
    addTableData() {
      if (this.flag) {
        // 表单预检验
        this.$refs.DictionaryRef.validate(async (valid) => {
          // console.log(valid)
          if (!valid) return
          this.isDisable = true
          const { data: res } = await this.$http.post('/sys/dict/save', this.DialogVisibleData)
          console.log(res)
          this.isDisable = false //执行请求后就不能点击了
          if (res.errorCode !== 200) return this.$message.error(res.message)
          this.$message.success('添加数据成功！')
          this.getDictionaryList()
          this.addDictionaryDialogVisible = false
        })
      } else {
        this.$refs.DictionaryRef.validate(async (valid) => {
          if (!valid) return
          this.isDisable = true
          const { data: res } = await this.$http.put('/sys/dict/update', this.DialogVisibleData)
          console.log(res)
          this.isDisable = false
          if (res.errorCode !== 200) return this.$message.error(res.message)
          this.$message.success('修改数据成功！')
          this.getDictionaryList()
          this.addDictionaryDialogVisible = false
        })
      }
    },
    // 点击修改按钮显示对话框
    async editTableData(Row) {
      const { data: res } = await this.$http.get('/sys/dict/info', { params: { id: Row.id } })
      console.log(res.data)
      this.getDictionaryType()
      this.addDictionaryDialogVisible = true
      this.flag = false
      this.disabledStr = true
      this.disabledSp = true
      this.DialogVisibleData.id = Row.id
      if (Row.parentId === 0) {
        this.DialogVisibleData.typename = ['一级菜单']
        this.DialogVisibleData.parentId = Row.parentId
      } else {
        this.tableData.map((items) => {
          // console.log(items.id)
          // console.log(Row.parentId)
          // console.log(Row.parentId)
          if (items.id == Row.parentId) {
            // console.log(items.id)
            this.DialogVisibleData.typename = ['二级菜单', items.code]
            this.DialogVisibleData.parentId = items.id
          } else {
            this.DialogVisibleData.typename = ['二级菜单', Row.parentCode]
          }
        })
      }
      this.DialogVisibleData.name = Row.name
      this.DialogVisibleData.type = Row.type
      this.DialogVisibleData.code = Row.code
      this.DialogVisibleData.value = Row.value
      this.DialogVisibleData.orderNumber = Row.orderNumber
      this.DialogVisibleData.remark = Row.remark
      this.DialogVisibleData.image = Row.image
      if (Row.image !== null && Row.image !== '') {
        // let fileListArr = Row.image.split(',')
        // console.log(fileListArr)
        let fileListObj = { name: Row.name + '.png', url: 'data:image/gif;base64,' + Row.image }
        this.fileList.push(fileListObj)
      }
    },
    // 监听对话框关闭事件重置表单
    resetFromData() {
      this.$refs.DictionaryRef.resetFields()
      this.fileList = []
    },
    // 监听文件状态改变
    handleChange(file, fileList) {
      // console.log(fileList)
      // console.log(fileList.slice(-1))
      this.fileList = fileList.slice(-1)
    },
    // 监听图片上传成功的事件
    handleSuccess(response) {
      console.log(response)
      // 1. 拼接得到一个图片信息对象
      // const picInfo = { name: '救治能力.jpeg', url: 'data:image/gif;base64,' + response.data }
      // console.log(picInfo)
      // 2. 将图片信息对象，push 到pics数组中
      // let imagesArr = this.DialogVisibleData.image.split(',')
      let imagesArr = []
      imagesArr.push(response.data)
      this.DialogVisibleData.image = imagesArr.join(',')
    },
    // 处理移除图片的操作
    handleRemove(file) {
      console.log(file)
      // 1. 获取将要删除的图片的临时路径
      const filePath = file.url
      // console.log(filePath.substr(22))
      let imagesList = this.DialogVisibleData.image.split(',')
      // console.log(imagesList)
      // 2. 从 pics 数组中，找到这个图片对应的索引值
      const i = imagesList.findIndex((x, i) => {
        if (x === filePath.substr(22)) {
          return i
        }
      })
      // console.log(i)
      // 3. 调用数组的 splice 方法，把图片信息对象，从 imagesList 数组中移除
      imagesList.splice(i, 1)
      console.log(imagesList)
      this.DialogVisibleData.image = imagesList.join(',')
    },
    //  实现表格单个删除功能
    async deleteTableBtn(id) {
      // 弹框询问用户是否删除数据
      const confirmResult = await this.$confirm('请确认该字典是否在使用中，删除在使用中的字典，可能会造成系统错误，是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      }).catch((err) => err)
      // 如果用户确认删除，则返回值为字符串 confirm
      // 如果用户取消了删除，则返回值为字符串 cancel
      // console.log(confirmResult)
      if (confirmResult !== 'confirm') {
        return this.$message.info('已取消删除')
      }
      const { data: res } = await this.$http.delete('/sys/dict/delete', { data: { ids: id } })
      // console.log(res)
      if (res.errorCode !== 200) return this.$message.error('删除数据失败！')
      this.$message.success('删除数据成功！')
      //此时已经实现删除操作，所以total的值需要减1，Math.ceil是向上取整，保证始终大于等于1
      const totalPage = Math.ceil((this.total - 1) / this.formInline.limit)
      //记录当前页码、记住删除最后一条数据时当前码是最后一页
      const pagenum = this.formInline.page > totalPage ? totalPage : this.formInline.page
      //实现跳转
      this.formInline.page = pagenum < 1 ? 1 : pagenum
      // 重新渲染（后面方法改为你的方法名）
      this.getDictionaryList()
    },
    // 当选择项发生变化时会触发该事件
    handleSelectionChange(val) {
      // console.log(val)
      let ids = []
      val.map(function (v) {
        ids.push(v.id)
      })
      this.ids = ids
      console.log(this.ids)
    },
    // 实现批量删除功能
    async allDeleteBtn() {
      console.log(this.ids)
      if (this.ids.length == 0) return this.$message.info('请先勾选要删除的数据！')
      let params = { ids: this.ids }
      const confirmResult = await this.$confirm('请确认该字典是否在使用中，删除在使用中的字典，可能会造成系统错误，是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      }).catch((err) => err)
      if (confirmResult !== 'confirm') {
        return this.$message.info('已取消删除')
      }
      const { data: res } = await this.$http.delete('/sys/dict/delete', { data: params })
      if (res.errorCode !== 200) return this.$message.error('删除数据失败！')
      this.$message.success('删除数据成功！')
      // totalPage 表示为删除n条数据除以每页显示的条数后、得出最后一页页数
      const totalPage = Math.ceil((this.total - this.ids.length) / this.formInline.limit)
      const pagenum = this.formInline.page > totalPage ? totalPage : this.formInline.page
      //实现跳转
      this.formInline.page = pagenum < 1 ? 1 : pagenum
      this.getDictionaryList()
    },
    // 表单查询功能
    async searchBtn() {
      this.formInline.page = 1
      this.formInline.limit = 10
      this.pictLoading = true
      const { data: res } = await this.$http.get('/sys/dict/list_page', { params: this.formInline })
      console.log(res)
      this.pictLoading = false
      if (res.errorCode !== 200) return this.$message.error('获取数据列表失败！')
      this.tableData = res.data.list
      this.total = res.data.totalCount
    },
    // 实现重置功能
    resetBtn() {
      this.$refs.queryFromRef.resetFields()
      this.searchBtn()
    },
  },
}
</script>
<style lang="less" scoped>
.el-card {
  .spnBorder {
    display: block;
    margin: 10px 0;
    width: 100%;
    border-bottom: 1px solid #ccc;
  }
  .el-table {
    .colRow .el-tag {
      margin: 0 0 5px 30px;
    }
  }

  .serachFrom {
    .btn {
      display: flex;
      flex-direction: row;
      justify-content: flex-end;
      padding-right: 20px;
      padding-bottom: 10px;
    }
  }
  .el-pagination {
    float: right;
    margin: 10px 20px;
  }
}
.el-dialog {
  .dialogBot {
    text-align: right !important;
    padding-right: 3%;
  }
  .el-cascader {
    width: 100%;
  }
}
</style>